﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace SpiderSync
{
    class Program
    {
        private static readonly SpiderSync _spiderSync = new SpiderSync();
        
        static void Main(string[] args)
        {
            try
            {
                parseCommandLine(args);
                _spiderSync.Run();             
            }
            catch (ArgumentException e)
            {
                if (e.Message.Length > 0)
                {
                    Output.Write(e.Message + "\r\n", MessageType.error);
                    ShowHelp();
                }
            }
            catch (Exception e)
            {
                Output.Write(e.Message, MessageType.error);
            }
        }

        /// <summary>
        /// Parse command line arguments and set up spidersync object
        /// </summary>
        /// <param name="args"></param>
        private static void parseCommandLine(string[] args)
        {
            List<String> excludePatterns = new List<string>();

            for (int i = 0; i < args.Length; i++)
            {
                // Parse command line switches
                if (args[i].StartsWith("/") || args[i].StartsWith("-"))
                {
                    switch (args[i].ToLower())
                    {
                        case "-d":
                        case "/d":
                            _spiderSync.Delay = Int16.Parse(args[++i]);
                            break;

                        case "-r":
                        case "/r":
                            _spiderSync.Retries = Int16.Parse(args[++i]);
                            break;

                        case "-v":
                        case "/v":
                            _spiderSync.Verbose = true;
                            Output.Verbose = true;
                            break;

                        case "--skip-initial-sync":
                        case "/skip-initial-sync":
                        case "-s":
                        case "/s":
                            _spiderSync.SkipInitialSync = true;
                            break;

                        case "--exclude":
                        case "/exclude":
                            if (!String.IsNullOrWhiteSpace(args[++i]))
                            {
                                excludePatterns.Add(args[i]);
                            }
                            break;

                        case "-?":
                        case "/?":
                            ShowHelp();
                            Environment.Exit(0);
                            break;

                        default:
                            throw new ArgumentException("Invalid command line argument: " + args[i]);
                    }

                    SpiderSync.excludePatterns = excludePatterns;
                    FilesystemUtils.excludePatterns = excludePatterns;
                }
                // Parse directory arguments
                else if (_spiderSync.SourceDir == null && _spiderSync.DestinationDir == null)
                {
                    _spiderSync.SourceDir = args[i++];
                    if (i < args.Length)
                    {
                        _spiderSync.DestinationDir = args[i];
                    }
                }
                else
                {
                    throw new ArgumentException("Invalid command line argument: " + args[i]);
                }
            }
        }

        /// <summary>
        /// Shows help message
        /// </summary>
        private static void ShowHelp()
        {
            string help = @"SpiderSync version {0}

Usage: {1} [/d DELAY] [/r RETRIES] [/v] [/skip-initial-sync|/s] [[/exclude PATTERN1] [/exclude PATT?RN2*]...] [/?] [SOURCE] [DESTINATION]
Options:
	/d  Minimal delay between the change operation in milliseconds
	/r  Max sync operation retry count
	/v  Verbose mode (show operation data instead of progress indicator)
	/skip-initial-sync /s  Skips initial synchronization
	/exclude Exclude wildcard pattern: Can be specified multiple times
	/?  Show this help
Arguments:
	[SOURCE]    Source directory
	[DESTINATION]   Destination directory
            ";

            Output.Write(String.Format(help, Assembly.GetExecutingAssembly().GetName().Version, Environment.GetCommandLineArgs()[0]), MessageType.message);
        }
    }
}
